package org.ly817.my.spring.core.ioc.bean.reader;

import org.ly817.my.spring.core.ioc.bean.BeanDefinition;
import org.ly817.my.spring.core.ioc.bean.PropertyValue;
import org.ly817.my.spring.core.ioc.io.ResourceLoader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;

/**
 * 读取xml文件到
 * Created by LuoYu on 2018/4/10.
 */
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {
        super(resourceLoader);
    }

    @Override
    public void loadBeanDefinitions(String location) throws Exception {
        InputStream inputStream = getResourceLoader().getResource(location).getInputStream();
        doLoadBeanDefinitions(inputStream);
    }

    protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        Document document = documentBuilder.parse(inputStream);
        // 解析xml中的bean属性
        registerBeanDefinitions(document);
        inputStream.close();
    }

    private void registerBeanDefinitions(Document document) {
        Element root = document.getDocumentElement();

        parseBeanDefinitions(root);
    }

    private void parseBeanDefinitions(Element root) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element element = (Element) node;
                processBeanDefinition(element);
            }
        }
    }

    private void processBeanDefinition(Element element) {
        String name = element.getAttribute("name");
        String className = element.getAttribute("class");
        BeanDefinition beanDefinition = new BeanDefinition();
        processProperty(element, beanDefinition);
        beanDefinition.setBeanClassName(className);
        // 将加载好的beanDefinition存入集合（登记）
        getRegistry().put(name, beanDefinition);
    }

    /**
     * 将从xml读取的bean信息注入到beanDefinition对象中 供beanFactory创建使用
     *
     * @param element
     * @param beanDefinition
     */
    private void processProperty(Element element, BeanDefinition beanDefinition) {
        NodeList propertyNode = element.getElementsByTagName("property");
        for (int i = 0; i < propertyNode.getLength(); i++) {
            Node node = propertyNode.item(i);
            if (node instanceof Element) {
                Element propertyEle = (Element) node;
                String name = propertyEle.getAttribute("name");
                String value = propertyEle.getAttribute("value");
                String refBeanName = propertyEle.getAttribute("ref");
                if ("".equals(refBeanName)) {
                    // 改bean对象不含有bean依赖
                    beanDefinition.getBeanPropertyValues().addPropertyValue(new PropertyValue(name, value));
                } else {
                    // 该bean对象有bean依赖
                    beanDefinition.getBeanPropertyValues().addPropertyValue(new PropertyValue(name, value, refBeanName));
                }
            }
        }
    }
}
